#pragma once

#include <thread>

// clang-format off
#include <libdaq/utils/base_queue.h>

#include "libdaq/backend/base_backend.h"
#include "libdaq/backend/backend_option.h"
#include "libdaq/device/base_device_config.h"
#include "libdaq/device/base_device_option.h"
// clang-format on

namespace libdaq {
namespace device {
/**
 * @brief 设备控制基类，开发者需要重点关注
 *
 * 该基类抽象了DAQ系列设备所有对外开放的方法
 *
 */
class LockzhinerBaseDevice {
public:
  LockzhinerBaseDevice();

  virtual ~LockzhinerBaseDevice();


  virtual bool BasicInfoGetDeviceType(); // 获取设备类型
  virtual bool BasicInfoGetHardwareVersion(); // 获取硬件版本
  virtual bool BasicInfoGetBootLoaderVersion(); // 获取BL锁版本
  virtual bool BasicInfoGetSoftwareVersion(); // 获取软件版本
  virtual const std::string &GetDeviceName(); // 设备名称
  virtual const std::string &GetDeviceType(); // 设备类型
  virtual const std::string &GetHardwareVersion(); // 硬件版本
  virtual const std::string &GetBootLoaderVersion(); // BL锁版本
  virtual const std::string &GetSoftwareVersion(); // 软件版本
  virtual std::string GetSN(); // 获取SN
  ///@}

  bool UseBackend(backend::LockzhinerBaseBackend* backend);

  static backend::USBOption GetUSBOption() { return {}; }

  virtual bool InitializeDevice(); // 初始化设备
  virtual bool ConnectedDevice(); // 连接设备
  virtual bool DisconnectedDevice(); // 断开设备

  virtual bool ConfigADCChannel(uint8_t channel); // 配置通道使能
  virtual bool ConfigADCTriggerSource(uint8_t source); // 配置触发源
  virtual bool ConfigADCVoltage(const std::vector<LockzhinerADCVoltage> &range_vector); // 配置电压量程
  virtual bool ConfigADCVoltage(const LockzhinerADCVoltage &range_vector); // 配置电压量程
  virtual bool ConfigADCSampleRate(LockzhinerADCSampleRate sample_rate); // 配置采样率
  virtual bool ConfigADCTrigger(LockzhinerADCTriggerType type,
                                LockzhinerADCTriggerMode mode,
                                LockzhinerADCChannel channel,
                                int level); // 配置触发方式、触发模式、触发通道
  virtual bool ConfigADCTriggerLength(uint32_t data_length); // 配置触发数据长度
  virtual bool ConfigTriggerTimeout(uint32_t timeout); // 配置超时时间
  virtual bool ConfigACDC(uint8_t channel); // AC/DC
  virtual bool StartADCCollection(); // 开始采集
  virtual bool StopADCCollection(); // 停止采集
  virtual bool ForceStopADCCollection(); // 强制停止采集
  virtual bool TryReadADCData(uint8_t channel, float *read_buffer); // 读取ADC通道数据
  virtual bool TryReadADCData(uint8_t channel, float *read_buffer, uint32_t read_size); // 读取ADC通道数据
  virtual bool TryReadADCData(uint8_t channel, float *read_buffer, uint32_t read_size, uint32_t timeout);

  bool ADCDataBufferIsEnough(uint8_t channel, uint32_t read_size, const bool *continue_waiting); // 判断数据缓存是否足够
  virtual void ClearDataBuffer(); // 清除数据缓存
  virtual bool ClearDataBuffer(uint8_t channel); // 清除指定通道的数据缓存

  const std::vector<LockzhinerADCSampleRate> &GetADCLegalSampleRate() const; // 获取支持的采样率
  uint32_t GetCurrentSampleRate() const; // 获取当前采样率
  const std::vector<LockzhinerADCVoltage> &GetADCLegalVoltage() const; // 获取支持的电压量程
  const std::vector<LockzhinerADCChannel> &GetADCLegalChannel() const; // 获取支持的通道
  uint32_t GetCurrentDataLength() const; // 获取当前数据长度
  LockzhinerADCTriggerType GetCurrentTriggerType() const; // 获取当前触发模式
  LockzhinerADCTriggerMode GetCurrentTriggerMode() const; // 获取当前触发方式
  uint8_t GetADCLegalChannelSize() const; // 获取支持的通道数量
  uint32_t GetADCBufferDataSize(int channel); // 获取某通道已缓存数据大小
  uint32_t GetADCBufferDataMaxSize() const; // 获取ADC缓存最大大小
  uint32_t GetADCLegalLengthMin() const; // 获取ADC触发最小长度
  uint32_t GetADCLegalLengthMax() const; // 获取ADC触发最大长度
  std::vector<LockzhinerADCVoltage> GetADCCurrentVoltage() const; // 获取当前电压量程
  bool ADCSampleRateIsLegal(const LockzhinerADCSampleRate &sample_rate); // 判断采样率是否合法
  bool ADCRangeIsLegal(const LockzhinerADCVoltage &range);  // 判断电压量程是否合法

  virtual bool SystemOpResetFPGA(); // 复位FPGA
  virtual bool SystemOpRestoreFactoryConfig(); // 恢复出厂配置

  virtual bool UpgradeFirmware(); // 更新固件
  virtual bool FirmwareInfo(uint32_t firmware_size); // 下发固件信息
  virtual bool SendFirmwareData(std::vector<uint8_t> &send_data); // 发送固件数据
  virtual bool CancelUpgradeFirmware(); // 取消更新固件

  virtual bool SystemOpEraseFirmware();

public:
  virtual bool BasicInfoSetHardwareVersion(const std::vector<uint8_t> &data);

  /** @name 系统操作相关函数
   *
   *  @brief 使用系统操作相关函数可配置、升级MCU/FPGA设备等操作。
   */

  /**
 * @brief 设置设备地址
 * @param 无
 * @return 是否配置成功
 */
  virtual bool SystemOpSetDeviceAddr(const uint8_t device_addr);

  /**
 * @brief 获取设备地址
 * @param addr 设备地址
 * @return 是否成功
 */
  virtual bool SystemOpGetDeviceAddr(uint8_t &addr);

  /**
  * @brief 获取设备名字
  * @param addr 设备名字
  * @return 是否成功
 */
  virtual bool SystemOpGetDeviceName(std::string &name);

  /**
 * @brief 设置设备名字
 * @param addr 设备名字
 * @return 是否成功
 */
  virtual bool SystemOpSetDeviceName(const std::string &name);

  /**
 * @brief 获取设备的mac地址
 * @param mac_address 设备的mac地址
 * @return 是否成功
 */
  virtual bool SystemOpGetMacAddr(std::vector<uint8_t> &mac_address);

  /**
 * @brief 设置设备的mac地址
 * @param mac_address 设备的mac地址
 * @return 是否成功
 */
  virtual bool SystemOpSetMacAddr(const std::vector<uint8_t> &mac_address);

  /**
 * @brief 获取设备的IP地址
 * @param ip      设备的IP地址
 * @param mask    设备的掩码
 * @param route   网关地址
 * @return 是否成功
 */
  virtual bool
  SystemOpGetDeviceNetInfo(std::vector<uint8_t> &ip, std::vector<uint8_t> &netmask, std::vector<uint8_t> &broadcast);

  /**
 * @brief 设置设备的IP地址
 * @param ip      设备的IP地址
 * @param mask    设备的掩码
 * @param route   网关地址
 * @return 是否成功
 */
  virtual bool SystemOpSetDeviceNetInfo(const std::vector<uint8_t> &ip, const std::vector<uint8_t> &netmask,
                                        const std::vector<uint8_t> &boradcast);

  /**
 * @brief 获取服务端信息
 * @param ip      服务端IP地址
 * @param port    服务端端口号
 * @return 是否成功
 */
  virtual bool SystemOpGetServerInfo(std::vector<uint8_t> &ip, uint32_t &port);

  /**
 * @brief 设置服务端信息
 * @param ip      服务端IP地址
 * @param port    服务端端口号
 * @return 是否成功
 */
  virtual bool SystemOpSetServerInfo(const std::vector<uint8_t> &ip, const uint32_t &port);

  /**
 * @brief 获取默认配置
 * @param config  默认配置
 * @return 是否成功
 */
  virtual bool ProductTestGetDefaultConfig(std::vector<uint8_t> &config);

  /**
 * @brief 设置SN
 * @param sn  sn序列号
 * @return 是否成功
 */
  virtual bool ProductTestSetSN(const std::vector<uint8_t> &sn);

  /**
 * @brief 获取SN
 * @return 是否成功
 */
  virtual bool ProductTestGetSN();

  /**
 * @brief 获取EEPROM的UID号
 * @param uid  uid序列号
 * @return 是否成功
 */
  virtual bool ProductTestGetEepromUID(std::vector<uint8_t> &uid);

  /**
 * @brief 开启验证UID
 * @param enable  是否开启，1为开启，0为关闭
 * @return 是否成功
 */
  virtual bool ProductTestSetEepromUIDVerify(uint8_t enable);

  virtual bool ConfigCalibration(const std::vector<uint8_t> &data); // 启动校正

  virtual bool ConfigOffsetCalibrationX1(const std::vector<uint8_t> &state); // 下发偏移校正参数x1档
  virtual bool ConfigGetOffsetCalibrationX1(std::vector<uint16_t> &state); // 获取偏移校正参数x1档
  virtual bool ConfigSaveOffsetCalibrationX1(const std::vector<uint8_t> &state); // 保存偏移校正参数x1档

  virtual bool ConfigOffsetCalibration_2_5(const std::vector<uint8_t> &state); // 下发偏移校正(2.5V)
  virtual bool ConfigGetOffsetCalibration_2_5(std::vector<uint8_t> &state); // 获取偏移校正参数(2.5V)
  virtual bool ConfigSaveOffsetCalibration_2_5(const std::vector<uint8_t> &state); // 保存偏移校正参数(2.5V)

  virtual bool ConfigOffsetCalibration_5(const std::vector<uint8_t> &state); // 下发偏移校正参数(5V)
  virtual bool ConfigGetOffsetCalibration_5(std::vector<uint8_t> &state); // 获取偏移校正参数(5V)
  virtual bool ConfigSaveOffsetCalibration_5(const std::vector<uint8_t> &state); // 保存偏移校正参数(5V)

  virtual bool ConfigOffsetCalibrationX10(const std::vector<uint8_t> &state); // 下发偏移校正x10档
  virtual bool ConfigGetOffsetCalibrationX10(std::vector<uint16_t> &state); // 获取偏移校正x10档
  virtual bool ConfigSaveOffsetCalibrationX10(const std::vector<uint8_t> &state); // 保存偏移校正x10档

  virtual bool ConfigGainCalibrationX1(const std::vector<uint8_t> &state); // 下发增益校正x1档
  virtual bool ConfigGetGainCalibrationX1(std::vector<uint16_t> &state);  // 获取增益校正x1档
  virtual bool ConfigSaveGainCalibrationX1(const std::vector<uint8_t> &state); // 保存增益校正x1档

  virtual bool ConfigGainCalibrationX2_5(const std::vector<uint8_t> &state); // 下发增益校正x2.5档
  virtual bool ConfigGetGainCalibrationX2_5(std::vector<uint16_t> &state); // 获取增益校正x2.5档
  virtual bool ConfigSaveGainCalibrationX2_5(const std::vector<uint8_t> &state); // 保存增益校正x2.5档

  virtual bool ConfigGainCalibrationX5(const std::vector<uint8_t> &state); // 下发增益校正x5档
  virtual bool ConfigGetGainCalibrationX5(std::vector<uint16_t> &state); // 获取增益校正x5档
  virtual bool ConfigSaveGainCalibrationX5(const std::vector<uint8_t> &state); // 保存增益校正x5档

  virtual bool ConfigGainCalibrationX10(const std::vector<uint8_t> &state); // 下发增益校正x10档
  virtual bool ConfigGetGainCalibrationX10(std::vector<uint16_t> &state); // 获取增益校正x10档
  virtual bool ConfigSaveGainCalibrationX10(const std::vector<uint8_t> &state); // 保存增益校正x10档

  virtual bool OpenOffsetCalibrationX1(std::vector<uint8_t> &data); // 打开偏移校正（x1档）
  virtual bool OpenOffsetCalibrationX10(std::vector<uint8_t> &data); // 打开偏移校正（x10档）
  virtual bool OpenGainCalibrationX1(std::vector<uint8_t> &data); // 打开增益校正（x1档）
  virtual bool OpenGainCalibrationX10(std::vector<uint8_t> &data); // 打开增益校正（x10档）
  virtual bool CloseCalibration(); // 关闭校正

  bool connected() const;
  UpgradeFirmwareStatus upgrade_firmware_status() const;

protected:
  virtual bool ParseCommandPacket(std::vector<unsigned char> &temp_parse_buffer, unsigned char &packet_index) = 0; // 解析命令包
  virtual bool ParseDataPacket(std::vector<unsigned char> &temp_parse_buffer, unsigned char &packet_index) = 0; // 解析数据包
  size_t CalculatePacketLength(size_t data_size); // 计算数据包长度
  virtual std::shared_ptr<uint8_t> BuildDataPacket(uint16_t command, const std::vector<uint8_t> &packet_data); // 构建数据包
  virtual bool SendCommand(uint16_t command, const std::vector<uint8_t> &data) = 0; // 发送命令
  virtual bool SendGetDeviceType(); // 获取设备类型
  virtual bool SendGetHardwareVersion(); // 获取硬件版本
  virtual bool SendGetBootLoaderVersion(); // 获取BL锁版本
  virtual bool SendGetSoftwareVersion(); // 获取软件版本
  virtual bool SendSetHardwareVersion(const std::vector<uint8_t> &data);

  virtual bool SendConnected();  // 连接设备
  virtual bool SendDisconnected(); // 断开设备
  virtual bool SendConfigADCTriggerSource(uint8_t source); // 设置触发源
  virtual bool SendConfigADCSampleRate(const LockzhinerADCSampleRate &sample_rate); // 设置采样率
  virtual bool SendConfigADCVoltageRange(const std::vector<LockzhinerADCVoltage> &range_vector); // 设置电压量程
  virtual bool SendEnableChannel(uint8_t channel); // 启用哪些通道
  virtual bool SendEnableDC(uint8_t channel); // 设置AC/DC
  virtual bool SendConfigTrigger(LockzhinerADCTriggerType type,
                                 LockzhinerADCTriggerMode mode,
                                 LockzhinerADCChannel channel,
                                 int level); // 设置触发方式、触发模式、触发通道
  virtual bool SendConfigReceiveDataLength(uint32_t data_length); // 设置数据长度
  virtual bool SendConfigTriggerTimeout(uint32_t timeout); // 设置触发超时时间

  virtual bool SendConfigCalibration(const std::vector<uint8_t> &data); // 启动校正

  virtual bool SendOffsetCalibrationX1(const std::vector<uint8_t> &state); // 下发偏移校正x1档
  virtual bool SendGetOffsetCalibrationX1();  // 获取偏移校正x1档
  virtual bool SendSaveOffsetCalibrationX1(const std::vector<uint8_t> &state); // 保存偏移校正x1档

  virtual bool SendOffsetCalibration_2_5(const std::vector<uint8_t> &state); // 下发偏移校正参数(2.5V)
  virtual bool SendGetOffsetCalibration_2_5(); // 获取偏移校正参数(2.5V)
  virtual bool SendSaveOffsetCalibration_2_5(const std::vector<uint8_t> &state); // 保存偏移校正参数(2.5V)

  virtual bool SendOffsetCalibration_5(const std::vector<uint8_t> &state); // 下发偏移校正参数(5V)
  virtual bool SendGetOffsetCalibration_5(); // 获取偏移校正参数(5V)
  virtual bool SendSaveOffsetCalibration_5(const std::vector<uint8_t> &state); // 保存偏移校正参数(5V)

  virtual bool SendOffsetCalibrationX10(const std::vector<uint8_t> &state); // 下发偏移校正x10档
  virtual bool SendGetOffsetCalibrationX10(); // 获取偏移校正x10档
  virtual bool SendSaveOffsetCalibrationX10(const std::vector<uint8_t> &state); // 保存偏移校正x10档

 virtual bool SendGainCalibrationX1(const std::vector<uint8_t> &state); // 下发增益校正x1档
  virtual bool SendGetGainCalibrationX1(); // 获取增益校正x1档
  virtual bool SendSaveGainCalibrationX1(const std::vector<uint8_t> &state); // 保存增益校正x1档

  virtual bool SendGainCalibrationX10(const std::vector<uint8_t> &state); // 下发增益校正x10档
  virtual bool SendGetGainCalibrationX10(); // 获取增益校正x10档
  virtual bool SendSaveGainCalibrationX10(const std::vector<uint8_t> &state); // 保存增益校正x10档



  virtual bool SendOpenOffsetCalibrationX1(std::vector<uint8_t> &data); // 打开偏移校正电路（x1档）
  virtual bool SendOpenOffsetCalibrationX10(std::vector<uint8_t> &data); // 打开偏移校正电路（x10档）
  virtual bool SendOpenGainCalibrationX1(std::vector<uint8_t> &data); // 打开增益校正电路（x1档）
  virtual bool SendOpenGainCalibrationX10(std::vector<uint8_t> &data); // 打开增益校正电路（x10档）

  virtual bool SendCloseCalibration(); // 关闭校正
  virtual bool SendStartCollection(); // 开始采集
  virtual bool SendStopCollection(); // 停止采集
  virtual bool SendForceStopCollection(); // 强制停止采集

protected:
  BaseDeviceOption device_option_; // 设备属性
  BasePacketOption packet_option_; // 数据包固定属性
  BaseADCOption adc_option_; // ADC属性
  BaseSystemOpOption system_option_; // 系统操作属性
  BaseProductTestOption product_test_option_; // 产品测试属性
  std::vector<std::shared_ptr<BaseQueue<float> > > channel_data_buffer_list_ = {}; // ADC通道数据缓存

  backend::LockzhinerBaseBackend* base_backend_ = nullptr; // 服务端
  BaseQueue<unsigned char> raw_data_buffer_{0}; // 原始缓存数据
  uint8_t packet_index_ = 0; // 发送包序号
  static const int PACKET_DATA_SIZE = 12;//12或者984
  bool connected_ = false; // 设备连接状态
  UpgradeFirmwareStatus upgrade_firmware_status_ = UpgradeFirmwareStatus::Idle; // 是否在升级固件状态
  std::unique_ptr<std::thread> parse_thread_ = nullptr;  // 解析线程
  std::atomic<bool> parse_thread_is_running_ = false; // 解析线程运行状态
  std::unique_ptr<std::thread> receive_thread_ = nullptr;  // 接收线程
  std::atomic<bool> receive_thread_is_running_ = false; // 接收线程运行状态

}; // class BaseDevice
} // namespace device
} // namespace libdaq
